package com.lincoln.framework.service;

import com.lincoln.framework.entity.Betting;
import com.lincoln.framework.entity.Game;
import com.lincoln.framework.entity.Member;
import com.lincoln.framework.hibernate.SimpleHibernateTemplate;
import com.lincoln.framework.utils.StringUtilsEx;
import com.lincoln.utils.DateUtils;
import org.hibernate.Criteria;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;

/**
 * 下注
 * Created by Lincoln on 2017/10/18.
 */
@Service
@Transactional
public class BettingService extends BaseService<Betting> {
    @Autowired
    public void setSessionFactory(SessionFactory sessionFactory) {
        dao = new SimpleHibernateTemplate<>(sessionFactory, Betting.class);
    }

    @Autowired
    MemberService memberService;
    @Autowired
    GameService gameService;

    /**
     * 查询数据
     *
     * @param criteria
     * @param parameters
     * @return
     */
    public Criteria createCriteria(Criteria criteria, Map<String, Object> parameters) {
        if (parameters.get("memberId") != null) {
            criteria.add(Restrictions.eq("member.id", parameters.get("memberId")));
        }
        if (parameters.get("score") != null) {
            criteria.add(Restrictions.eq("score", parameters.get("score")));
        }
        if (parameters.get("win") != null) {
            criteria.add(Restrictions.eq("win", parameters.get("score")));
        }
        if (!StringUtilsEx.isNullOrEmpty((String) parameters.get("content"))) {
            criteria.add(Restrictions.eq("content", parameters.get("content")));
        }
        if (parameters.get("result") != null) {
            criteria.add(Restrictions.eq("result", parameters.get("result")));
        }
        return criteria;
    }

    /**
     * 查询当天下注情况
     */
    public List<Betting> getTodayBatting(Long memberId) {
        Criteria criteria = this.dao.createCriteria();
        criteria.add(Restrictions.ge("createTime", DateUtils.getTodayDateStart()));
        criteria.add(Restrictions.le("createTime", DateUtils.getTodayDateEnd()));
        if (memberId != null && memberId > 0) {
            criteria.add(Restrictions.eq("member.id", memberId));
        }
        return this.findList(criteria);
    }

    /**
     * 查询最后一次下注
     */
    public Betting getLastBetting(Long memberId) {
        Criteria criteria = this.dao.createCriteria();
        if (memberId != null && memberId > 0) {
            criteria.add(Restrictions.eq("member.id", memberId));
        }
        criteria.addOrder(Order.desc("createTime"));
        List<Betting> list = this.findList(criteria);
        if (list == null || list.size() <= 0) {
            return null;
        }
        return list.get(0);
    }

    public double sumTodayBatting(Long memberId) {
        List<Betting> list = getTodayBatting(memberId);
        double result = 0;
        for (Betting betting : list) {
            if (betting.getScore() != null && betting.getScore() >= 0) {
                result += betting.getScore();
            }
        }
        return result;
    }

    /**
     * 查询今日下注的订单数
     *
     * @param memberId
     * @return
     */
    public int countOrder(Long memberId) {
        List list = getTodayBatting(memberId);
        return list == null ? 0 : list.size();
    }

    /**
     * 查询今日下注中奖的订单
     *
     * @param memberId
     * @return
     */
    public List<Betting> queryTodayWinBatting(Long memberId) {
        Criteria criteria = this.dao.createCriteria();
        criteria.add(Restrictions.ge("createTime", DateUtils.getTodayDateStart()));
        criteria.add(Restrictions.le("createTime", DateUtils.getTodayDateEnd()));
        criteria.add(Restrictions.eq("result", Betting.RESULT_WIN));
        if (memberId != null && memberId > 0) {
            criteria.add(Restrictions.eq("member.id", memberId));
        }
        return this.findList(criteria);
    }

    /**
     * 查询某用户在某次游戏下注情况
     *
     * @param gameId
     * @param memberId
     * @return
     */
    public List<Betting> queryBettingByGameAndMember(long gameId, long memberId) {
        Criteria criteria = this.dao.createCriteria();
        criteria.add(Restrictions.eq("game.id", gameId));
        criteria.add(Restrictions.eq("member.id", memberId));
        return this.findList(criteria);
    }

    /**
     * 删除某用户在某次游戏下注情况
     *
     * @param gameId
     * @param memberId
     * @return
     */
    public void deleteByGameIdAndMemberId(long gameId, long memberId) {
        List<Betting> bettings = queryBettingByGameAndMember(gameId, memberId);
        if (bettings != null && bettings.size() > 0) {
            for (Betting betting : bettings) {
                Member member = betting.getMember();
                member.setAllUse(member.getAllUse() - betting.getScore());
                memberService.save(member);
                delete(betting);
            }
        }
    }

    /**
     * 查询游戏下注情况
     *
     * @param gameId
     * @return
     */
    public List<Betting> queryBettingByGame(long gameId) {
        Criteria criteria = this.dao.createCriteria();
        criteria.add(Restrictions.eq("game.id", gameId));
        return this.findList(criteria);
    }

    /**
     * 查询今日下注中奖的订单总数
     *
     * @param memberId
     * @return
     */
    public int countTodayWinBatting(Long memberId) {
        List<Betting> list = queryTodayWinBatting(memberId);
        return list == null ? 0 : list.size();
    }

    /**
     * 查询今日中奖金额总数(盈亏)
     *
     * @param memberId
     * @return
     */
    public double countTodayWin(Long memberId) {
        double result = 0;
        List<Betting> list = queryTodayWinBatting(memberId);
        for (Betting betting : list) {
            if (betting.getResult() == Betting.RESULT_WIN) {
                result += (betting.getWin() == null ? 0 : betting.getWin());
            }
        }
        return result;
    }

    /**
     * 将所有未处理的下注统一设置为未中奖
     */
    public void unWinAllNoDeal() {
        Criteria criteria = this.dao.createCriteria();
        criteria.add(Restrictions.isNull("result"));
        List<Betting> list = this.dao.findByCriteria(criteria);
        if (list != null && list.size() > 0) {
            for (Betting betting : list) {
                betting.setWin(new Double(0));
                betting.setResult(Betting.RESULT_LOSE);
                save(betting);
            }
        }
    }
}
